#pragma once



#define _WINSOCK_DEPRECATED_NO_WARNINGS 
#include <iostream>
#include <string.h>
#include <event2/event.h>
#include <event2/bufferevent.h>
#include <event2/listener.h>
#include <event2/thread.h>
#include <event2/buffer.h>

#ifdef _WIN32
#include <windows.h>
#include <time.h>
#include <ws2tcpip.h>
#else
#include <unistd.h>
#include <arpa/inet.h>
#endif


#include "NuTradeSDK/NuStructs.h"
#include "TradeDemoSpi.h"
#include "LFDataStruct.h"
#include "sys_message.h"
#include "QmtConst.h"
#include <mutex>
#include "tscns.h"

struct InitData {
	TSCNS ns;
	static InitData & GetInstance() {
		static InitData instance;
		return instance;
	}

	void set_ctx(void * p) {
		ctx = p;
		ns.init();
	}
	void* get_ctx() {
		if (!ctx) {
			cout << "ctx need init" << endl;
		}
		return ctx;
	}

	void set_connect(bool p) {
		connect = p;
	}
	bool get_connect() {
		return connect;
	}


	void set_bev(bufferevent * p) {
		bev.reset(p, [](bufferevent *q) { });
		//bev.reset(p);
		//bev = p;
	}
	bufferevent * get_bev() {
		if (!bev) {
			cout << "bev need init" << endl;
		}
		return bev.get();
	}

private:
	void *ctx = nullptr; // class ctx
	bool connect = false;
	shared_ptr<bufferevent> bev = nullptr;


};

template<typename T>
class OrderPolicy {
public:
	static int m_request;
	static void order_logic(int type, void * buf, void * arg) {
		T *ctx = (T *)arg;
		if (!ctx  ) {
			printf("g_ctx need init !\n");
			return;
		}
	
		// api shoud check

		auto ptr = ctx->get_ptr();
		if (!ptr) {
			printf(" smartptr desctructed !!!");
		}
		

		short msg_type = type;

		switch (msg_type) {
		case MSG_TYPE_TRADE_ENGINE_LOGIN: {


			if (ptr->m_login) {
			//	p->head.msg_type = MSG_TYPE_TRADE_ENGINE_OPEN;

			}
			else {
			//	p->head.msg_type = MSG_TYPE_TRADE_ENGINE_CLOSE;
			}

			//const char *data = reinterpret_cast<const char *>(p);
			//bufferevent_write(g_bev, data, strlen(data) + 1);
			break;
		}

		case 20: {

			nusdk::OrderStockReq order;
			LFInputOrderField *p = reinterpret_cast<LFInputOrderField *>  (buf);
			cout << "msg order !!!"<<endl;
			order.accountKey = ptr->m_stockAccount;

			char  exchangeID[16];         ///< 市场代码
			if (p->exchange == '1') {//上海
				strcpy2(order.exchangeID, "SH");
			}
			else if (p->exchange == '2') {

				strcpy2(order.exchangeID, "SZ");

			}
			strcpy2(order.instrumentID, p->ticker);

			cout << "SIDE : " << p->side << endl;
			if (p->side == LF_CHAR_Buy) {
				order.orderType = nusdk::NU_OPT_BUY;
			}
			else {

				printf("unkknown type!\n");

			}
			order.orderVolume = p->volume;
			order.priceType = nusdk::NU_PRTP_FIX;
			order.price = p->price;
			strcpy2(order.remark, "net_remark");

			int rlt = ptr->m_pApi->ReqOrderTicket(m_request++, order);

			break;
		}

		case 23: {

			nusdk::CancelOrderStockReq param1;
			LFOrderActionField *p = reinterpret_cast<LFOrderActionField *>  (buf);
			cout << "msg cancel order !!!" << endl;
			param1.accountKey = ptr->m_stockAccount;

			{
				//以订单编号撤单，orderID传订单编号，市场代码和委托编号置空
				param1.accountKey = ptr->m_stockAccount;
				param1.orderID = 0; //订单编号
				if (p->exchange == '1') {//上海
					strcpy2(param1.exchangeID, "SH");
				}
				else if (p->exchange == '2') {

					strcpy2(param1.exchangeID, "SZ");

				}
				strcpy2(param1.orderSysID, to_string(p->sys_id).c_str()); //委托编号
			}
			ptr->m_pApi->ReqCancelTicket(m_request++, param1);
			break;

		}

		}
	}
};

template<typename T>
int OrderPolicy<T>::m_request = 0;




//----------------------------------------------------------------------------------------------------------------------------------
template<
	typename T,
	template<class T> class  OrderPolicy
>

class NetManager :public OrderPolicy< NetManager<T,OrderPolicy>> {

public:
	NetManager(shared_ptr<T> &spi) :m_spi(spi) {
	
	}

	/*
	thread net;
	//  this for mutex
	NetManager(const NetManager &src)  {

	}
	NetManager(const NetManager &&src)  {

	}
	*/


	void receive_msg_from_td(const char * msg, int len) {

		if (!InitData::GetInstance().get_connect()) {
			printf("no connect \n");
			return;
		}

		//写数据给客户端
		printf("--------------------------------receive_msg_from_td---------------------------\n");
	//	lck.lock();
		int rlt = bufferevent_write(InitData::GetInstance().get_bev(), msg, len);
	//	lck.unlock();
		//::Sleep(600);

		if (rlt < 0) {
			//发送异常
		}
	}


	static void cb_listener(struct evconnlistener *listener, evutil_socket_t fd, struct sockaddr *addr, int len, void *ptr)
	{



		int enable = 1;
		if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (const char *)&enable, sizeof(enable)) < 0)
			printf("Consensus-side: TCP_NODELAY SETTING ERROR!\n");



		struct sockaddr_in* client = (sockaddr_in*)addr;
		cout << "connect new client: " << inet_ntoa(client->sin_addr) << "::" << ntohs(client->sin_port) << endl;

		struct event_base *base = (struct event_base*)ptr;

		//添加新事件
		struct bufferevent *bev;
		bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE | BEV_OPT_THREADSAFE);
		InitData::GetInstance().set_bev(bev);
		//给bufferevent缓冲区设置回调
		bufferevent_setcb(bev, read_cb, write_cb, event_cb, InitData::GetInstance().get_ctx());

		//启动 bufferevent的 读缓冲区。默认是disable 的
		bufferevent_enable(bev, EV_READ); //#define EV_WRITE	0x04
		bufferevent_enable(bev, EV_WRITE); //#define EV_WRITE	0x04

		InitData::GetInstance().set_connect(true);
	}


	static 	void event_cb(struct bufferevent *bev, short events, void *g_ctx)
	{

		if (events & BEV_EVENT_EOF)
		{
			cout << "connection closed:" << endl;
		}
		else if (events & BEV_EVENT_ERROR)
		{
			cout << "some other error !" << endl;
		}

		bufferevent_free(bev);
		cout << "bufferevent 资源已经被释放..." << endl;
	}

	void init() {

		WORD wVersionRequested;
		WSADATA wsaData;
		wVersionRequested = MAKEWORD(2, 2);
		(void)WSAStartup(wVersionRequested, &wsaData);

		//init server
		struct sockaddr_in serv;

		memset(&serv, 0, sizeof(serv));
		serv.sin_family = AF_INET;
		serv.sin_port = htons(9002);
		serv.sin_addr.s_addr = htonl(INADDR_ANY);

#ifdef WIN32

		evthread_use_windows_threads();//win上设置

#else

		evthread_use_pthreads();//unix上设置

#endif

		//创建 event_base
		struct event_base * base;
		base = event_base_new();

		//创建套接字
		//绑定
		//接收连接请求
		struct evconnlistener* listener;
		listener = evconnlistener_new_bind(base, cb_listener, base, LEV_OPT_CLOSE_ON_FREE | BEV_OPT_THREADSAFE, 36, (struct  sockaddr*)&serv, sizeof(serv));

		//启动循环监听
		event_base_dispatch(base);
		evconnlistener_free(listener);
		event_base_free(base);

	}


	//從策略讀到數據
	static void read_cb(struct bufferevent* bev, void* arg)
	{
		char buf_event[4096];
		int n;
		//const char *line = "ddddddddddddddddddddd";
		//bufferevent_write(g_bev, line, strlen(line) + 1);
		struct evbuffer *input = bufferevent_get_input(InitData::GetInstance().get_bev());
		size_t lens = evbuffer_get_length(input);

		char * rline = buf_event;
		//rline = evbuffer_readln(input, &len, evbuffer_eol_style::EVBUFFER_EOL_CRLF);
		bufferevent_read(InitData::GetInstance().get_bev(), buf_event,lens);
		while (lens > 0)
		{	
			char type[3] = {};
			//bufferevent_read(bev, type, sizeof("20"));
			memcpy(type, rline,3);
			rline = rline + 3;
			lens = lens - 3;

			if (stoi(type) == stoi(QMT_ORDER)) {
				char buf[128] = {};
				cout << "nano :" << InitData::GetInstance().ns.rdns() << endl;
				FileAdapter::GetInstance().flush_to_file("rtn.log", "insert order nano :" + to_string(InitData::GetInstance().ns.rdns()) + "\n");
				LFInputOrderField *p = reinterpret_cast<LFInputOrderField *>  (rline );
				order_logic(stoi(type), rline, InitData::GetInstance().get_ctx());
				cout << p->price << endl;
				rline = rline + sizeof(LFInputOrderField) ;
				lens = lens - sizeof(LFInputOrderField) ;
				//bufferevent_read(bev, buf, sizeof(LFInputOrderField));
			}
			else if (stoi(type) == stoi(QMT_CANCEL_ORDER)) {
				char buf[128] = {};
				cout << sizeof(LFOrderActionField) << endl;
				LFOrderActionField *q = reinterpret_cast<LFOrderActionField *>  (rline);
				cout << "cancel order_id " << q->order_id << endl;
				cout << "cancel sys_id " << q->sys_id << endl;

				order_logic(stoi(type), rline, InitData::GetInstance().get_ctx());
				rline = rline + sizeof(LFOrderActionField);
				lens = lens - sizeof(LFOrderActionField);
			}
			else {
				break;
			}

		}


	}

	static void write_cb(struct bufferevent* bev, void* arg)
	{
		cout << "I'm 服务器，成功写数据给客户端，写缓冲回调函数被调用..." << endl;
	}

	shared_ptr<T> get_ptr() {
	
		return m_spi.lock();
	
	}
public:

	using OrderPolicy< NetManager>::order_logic;
	weak_ptr<T> m_spi;

};

